package io.eyer.nio.core.event;

import io.eyer.nio.core.session.Session;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Date;

/**
 * Created by 青木 on 2015/8/17.
 * NIO 连接器，用于连接远程server
 */
public class Connector extends NioAbstract<Session> {
    private static Logger logger = LoggerFactory.getLogger(Connector.class);

    public Connector(ReactorPool reactorPool) throws IOException {
        super(reactorPool);
    }

    @Override
    public void handleKey(SelectionKey key) {
        if (key.isValid()) {
            if (key.isConnectable()) {
                Session session = (Session) key.attachment();
                try {
                    while (!session.getSocketChannel().finishConnect()) {
                        System.out.println("check finish connection");
                    }
                    key.interestOps(0);
                    key.cancel();
                    reactorPool.register(session.getSocketChannel(), session);
                } catch (Exception e) {
                    session.getLatch().countDown();
                    session.getRegLeach().countDown();
                    session.status = Session.Status.CLOSED;
                    logger.error(e.getMessage(), e);
                }
            } else {
                key.cancel();
            }
        }
    }


    public Session connect(String host, int port) throws IOException, InterruptedException {
        InetSocketAddress addr = new InetSocketAddress(host, port);
        SocketChannel socketChannel = SocketChannel.open();
        socketChannel.configureBlocking(false);
        Session session = new Session(socketChannel, null, new Date());

        super.registeredQueue.offer(session);
        this.selector.wakeup();
        session.getRegLeach().await();
        socketChannel.connect(addr);
        session.getLatch().await();
        return session;
    }


    @Override
    protected void handleRegistered(Session session, Selector selector) throws ClosedChannelException {
        SelectionKey key = session.getSocketChannel().register(selector, SelectionKey.OP_CONNECT, session);
        session.setKey(key);
        session.getRegLeach().countDown();
    }

    @Override
    public Logger getLogger() {
        return logger;
    }
}
